package com.ruoyi.ruoyiqywechat.controller;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.uuid.UUID;
import com.ruoyi.common.qy.domain.User;
import com.ruoyi.common.qy.vo.VideoInfoVo;
import com.ruoyi.common.redis.utils.RedisUtil;
import com.ruoyi.ruoyiqywechat.domain.MembershipPlanNew;
import com.ruoyi.ruoyiqywechat.domain.OrderQy;
import com.ruoyi.ruoyiqywechat.domain.UserMembership;
import com.ruoyi.ruoyiqywechat.domain.WxchatCallbackSuccessData;
import com.ruoyi.ruoyiqywechat.mapper.OrderQyMapper;
import com.ruoyi.ruoyiqywechat.service.*;
import com.ruoyi.ruoyiqywechat.service.qywechat.QyMessageService;
import com.ruoyi.ruoyiqywechat.wx.pay.config.PayConstants;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;

import javax.jws.Oneway;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("callback")
public class CallbackController {



    @Autowired
    private VideoService videoService;

    @Autowired
    private OrderQyMapper orderQyMapper;

    @Autowired
    private IUserMembershipService userMembershipService;

    @Autowired
    private IMembershipPlanNewService membershipPlanNewService;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private ChatAiService chatAiService;

    @Autowired
    private QyMessageService qyMessageService;


    @GetMapping("/tuiSong")
    public void tuiSong(@RequestParam("userId") String userId){
        //发送会员连接去绑定并支付
        HashMap<String, Object> mapMember = new HashMap<>();
        mapMember.put("conversation_id", "S:" + userId);
        mapMember.put("title", "会员套餐待支付");
        mapMember.put("description", "点击支付，开启您的会员之旅");//uuid作为唯一标识传参数
        mapMember.put("url", "https://vx.jxhaoliu.cn/h5_litui_vip/#/pages/vip/vip?sendUserId="+userId);
        mapMember.put("image_url", "https://wx.qlogo.cn/mmhead/Q3auHgzwzM6DgpZJlicKaZGicIzF6TTAeCoTAa4VMk86MQqxLLA9tRZw/0");
        qyMessageService.send_gh(mapMember);
    }
    @GetMapping("/memberExperTime")
    public boolean memberExperTime(@RequestParam("userId") String userId){

        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getTagId,userId);
        User user = userService.getOne(userLambdaQueryWrapper);
        if(user == null){
            HashMap<String, Object> mapMember = new HashMap<>();
            mapMember.put("conversation_id", "S:" + userId);
            String str = "还存在免费次数未用完，请先用完后授权再查询";
            mapMember.put("content", str);
            qyMessageService.send_private(mapMember);
            return false;
        }

        LambdaQueryWrapper<UserMembership> userMembershipLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userMembershipLambdaQueryWrapper.eq(UserMembership::getStatus,1)
                        .eq(UserMembership::getUserId,user.getUid());
        UserMembership userMembership = userMembershipService.getOne(userMembershipLambdaQueryWrapper);
        if(userMembership == null){
            HashMap<String, Object> mapMember = new HashMap<>();
            mapMember.put("conversation_id", "S:" + userId);
            String str = "不存在会员信息!";
            mapMember.put("content", str);
            qyMessageService.send_private(mapMember);
            return false;
        }
        Date startTime = userMembership.getStartTime();
        Date endTime = userMembership.getEndTime();
        HashMap<String, Object> mapMember = new HashMap<>();
        mapMember.put("conversation_id", "S:" + userId);
        String str = "尊敬的会员，您开通的是套餐"+userMembership.getPlanId()+",会员开通时间："+startTime+" - "+endTime;
        mapMember.put("content", str);
        qyMessageService.send_private(mapMember);
        return true;
    }

    public boolean isMember(String userId){
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getTagId,userId);
        User user = userService.getOne(userLambdaQueryWrapper);
        if(user == null){
            return true;
        }

        LambdaQueryWrapper<UserMembership> userMembershipLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userMembershipLambdaQueryWrapper.eq(UserMembership::getStatus,1)
                .eq(UserMembership::getUserId,user.getUid());
        UserMembership userMembership = userMembershipService.getOne(userMembershipLambdaQueryWrapper);
        return userMembership == null;
    }

    @PostMapping("qyMsg")
    public void  qyMsg(@RequestBody String json){
        System.out.println("回调消息："+json);
        JSONObject jsonObject = JSONObject.parseObject(json);
        JSONObject data = jsonObject.getJSONObject("data");
        String guid = jsonObject.getString("guid");
        long notify_type = jsonObject.getLongValue("notify_type");
        if(141 == data.getLongValue("content_type")){
            videoService.saveRedisVideo(data);
        }else  if(78 == data.getLongValue("content_type")){
            System.out.println("小程序信息/////");
        }
        //单聊中的消息
        if(notify_type == (11010) ){
            String sender = data.getString("sender");//发送者
            //发送者不是力推助手自己的时候   判断是否是待激活的用户
            if(!"1688852859354773".equals(sender) && isMember(sender)){
                String senderName = data.getString("sender_name");//发送者
                String content = data.getString("content");//消息内容
                int msgType = data.getIntValue("msg_type");//消息的类型2
                if(msgType == 2){
                    //文本消息
                    chatAiService.sendText(content,sender);
                }
            }
        }
    }
    @PostMapping("paycallback")
    public synchronized Map<String, String> callBack(@RequestBody JSONObject jsonObject) {
        System.out.println("微信支付回调通知结果：" + jsonObject);
        try {
            String key = PayConstants.API_V3KEY;
            String json = jsonObject.toString();
            String event_type = (String) JSONUtil.getByPath(JSONUtil.parse(json), "event_type");
            System.out.println("当前回调通知类型是：" + event_type);
            String associated_data = (String) JSONUtil.getByPath(JSONUtil.parse(json), "resource.associated_data");
            String ciphertext = (String) JSONUtil.getByPath(JSONUtil.parse(json), "resource.ciphertext");
            String nonce = (String) JSONUtil.getByPath(JSONUtil.parse(json), "resource.nonce");
            System.out.println("解密前的数据：" + associated_data+"========"+ciphertext+"========="+nonce);
            String decryptData = new AesUtil(key.getBytes(StandardCharsets.UTF_8)).decryptToString(associated_data.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), ciphertext);
            System.out.println("解密后的数据：" + decryptData);
            //验签成功
            JSONObject decryptDataObj = JSONObject.parseObject(decryptData, JSONObject.class);
            //decryptDataObj 为解码后的obj，其内容如下。之后便是验签成功后的业务处理
            //{
            //	"sp_appid": "wx8888888888888888",
            //	"sp_mchid": "1230000109",
            //	"sub_appid": "wxd678efh567hg6999",
            //	"sub_mchid": "1900000109",
            //	"out_trade_no": "1217752501201407033233368018",
            //	"trade_state_desc": "支付成功",
            //	"trade_type": "MICROPAY",
            //	"attach": "自定义数据",
            //	"transaction_id": "1217752501201407033233368018",
            //	"trade_state": "SUCCESS",
            //	"bank_type": "CMC",
            //	"success_time": "2018-06-08T10:34:56+08:00",
            //    ...
            //	"payer": {
            //		"openid": "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o"
            //	},
            //	"scene_info": {
            //		"device_id": "013467007045764"
            //	}
            //}
            WxchatCallbackSuccessData wxchatCallbackSuccessData = new WxchatCallbackSuccessData();
            wxchatCallbackSuccessData.setOrderUUID(decryptDataObj.getString("out_trade_no"));
            wxchatCallbackSuccessData.setSuccessTime(decryptDataObj.getString("success_time"));
            wxchatCallbackSuccessData.setTradetype(decryptDataObj.getString("trade_type"));
            wxchatCallbackSuccessData.setTradestate(decryptDataObj.getString("trade_state"));
            wxchatCallbackSuccessData.setTransactionId(decryptDataObj.getString("transaction_id"));
            wxchatCallbackSuccessData.setAttachType(decryptDataObj.getString("attach"));
            System.out.println("组合好的通知参数：" + wxchatCallbackSuccessData);
            //修改订单状态
            //修改支付时间
            //判断是否需要回传
            QueryWrapper<OrderQy> orderQyQueryWrapper = new QueryWrapper<>();
            orderQyQueryWrapper.lambda().eq(OrderQy::getOrderNo,wxchatCallbackSuccessData.getOrderUUID());
            OrderQy orderQy = orderQyMapper.selectOne(orderQyQueryWrapper);
            if (orderQy != null && orderQy.getStatus() == 0) {
                orderQy.setPayTime(DateUtils.getNowDate());//支付时间
                orderQy.setStatus(1);//支付状态
                orderQyMapper.updateById(orderQy);


                //添加用户和会员之间的关联
                UserMembership userMembership = new UserMembership();
                userMembership.setUserId(orderQy.getUserId());
                userMembership.setPlanId(orderQy.getPlanId());
                MembershipPlanNew membershipPlanNew = membershipPlanNewService.selectMembershipPlanNewById(orderQy.getPlanId());
                LocalDateTime result = currentTimePlusMonths(membershipPlanNew.getDurationMonths());

                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

                System.out.println("当前时间: " + LocalDateTime.now().format(formatter));
                System.out.println("加" + membershipPlanNew.getDurationMonths() + "个月后的时间: " + result.format(formatter));
                // 将LocalDateTime转换为Date
                Date startDate = Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant());
                Date endDate = Date.from(result.atZone(ZoneId.systemDefault()).toInstant());
                userMembership.setStartTime(startDate);
                userMembership.setEndTime(endDate);

                userMembership.setStatus(1);//有效
                userMembership.setAutoRenew(0);//关闭
                userMembershipService.insertUserMembership(userMembership);
                String memberKey = "member:" + orderQy.getUserId() + ":" + orderQy.getPlanId();
                try {
                    redisUtil.getRedisTemplate().expireAt(memberKey, endDate);
                }catch (Exception e){
                    System.out.println("【支付后设置会员过期失败redis...】"+memberKey);
                }


                //更改用户自身详细信息
                User user = userService.getById(orderQy.getUserId());
                user.setIsFenjian(true);
                user.setFenjianTime(startDate);
                userService.updateById(user);
            }
        } catch (Exception e) {
            System.out.println("支付回调异常" + e);
            Map<String, String> res = new HashMap<>();
            res.put("code", "ERROR");
            res.put("message", "成功");
            return res;
        }
        Map<String, String> res = new HashMap<>();
        res.put("code", "SUCCESS");
        res.put("message", "成功");
        return res;
    }
    /**
     * 当前时间加上n个月份
     * @param months 要添加的月数
     * @return 加上月份后的时间
     */
    public static LocalDateTime currentTimePlusMonths(long months) {
        return LocalDateTime.now().plusMonths(months);
    }
}
